﻿using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.Geometry;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml.Linq;

namespace AutoCadConvert
{
    public class Points: Collection
    {
        public Point m_Center = new Point();
        public List<Point> m_Points = new List<Point>();

        public Points(House house) : base(house){}
        public override void AddData(Entity value)
        {
            base.AddData(value);
            if (value is Autodesk.AutoCAD.DatabaseServices.Line)
            {
                Autodesk.AutoCAD.DatabaseServices.Line entity = value as Autodesk.AutoCAD.DatabaseServices.Line;
                Point pSta = new Point(entity.StartPoint);
                Point pEd = new Point(entity.EndPoint);
                if (m_Points.Find(new Predicate<Point>(o => o == pSta))==null)
                {
                    pSta.index = m_Points.Count;
                    pSta.IsLogicPoint = entity.Layer == LayerName.instance()[0] ? false : true;
                    m_Points.Add(pSta);
                }
                else
                {
                    m_Points[m_Points.IndexOf(pSta)].IsLogicPoint = entity.Layer == LayerName.instance()[0] ? false : true;
                    m_Points[m_Points.IndexOf(pSta)].refCount++;
                }
                //查找点
                if (m_Points.Find(new Predicate<Point>(o => o == pEd)) == null)
                {
                    pEd.index = m_Points.Count;
                    pEd.IsLogicPoint = entity.Layer == LayerName.instance()[0] ? false : true;
                    m_Points.Add(pEd);
                }
                else
                {
                    m_Points[m_Points.IndexOf(pEd)].IsLogicPoint = entity.Layer == LayerName.instance()[0] ? false : true;
                    m_Points[m_Points.IndexOf(pEd)].refCount++;
                }
            }
            else if (value is Autodesk.AutoCAD.DatabaseServices.Polyline)
            {
                Autodesk.AutoCAD.DatabaseServices.Polyline entity = value as Autodesk.AutoCAD.DatabaseServices.Polyline;
                for (int i = 0; i < entity.NumberOfVertices; i++)
                {
                    if (SegmentType.Line == entity.GetSegmentType(i))
                    {
                        Point pSta = new Point(entity.GetLineSegmentAt(i).StartPoint, entity.Layer== LayerName.instance()[0] ? false:true);
                        Point pEd = new Point(entity.GetLineSegmentAt(i).EndPoint, entity.Layer == LayerName.instance()[0] ? false : true);
                        if (m_Points.Find(new Predicate<Point>(o => o == pSta)) == null)
                        {
                            pSta.index = m_Points.Count;
                            pSta.IsLogicPoint = entity.Layer == LayerName.instance()[0] ? false : true;
                            m_Points.Add(pSta);
                        }
                        else
                        {
                            m_Points[m_Points.IndexOf(pSta)].IsLogicPoint = entity.Layer == LayerName.instance()[0] ? false : true;
                            m_Points[m_Points.IndexOf(pSta)].refCount++;
                        }
                        //查找点
                        if (m_Points.Find(new Predicate<Point>(o => o == pEd)) == null)
                        {
                            pEd.index = m_Points.Count;
                            pEd.IsLogicPoint = entity.Layer == LayerName.instance()[0] ? false : true;
                            m_Points.Add(pEd);
                        }
                        else
                        {
                            m_Points[m_Points.IndexOf(pEd)].IsLogicPoint = entity.Layer == LayerName.instance()[0] ? false : true;
                            m_Points[m_Points.IndexOf(pEd)].refCount++;
                        }
                    }
                }
            }
        }
        public override void AjustLineAndPoint()
        {
            //Point加减法refCount变化
            if (m_Points.Count > 0)
            {
                m_Center = (new Point() { X = m_Points.Max(o => o.X) + m_Points.Min(o => o.X), Y = m_Points.Max(o => o.Y) + m_Points.Min(o => o.Y) }) / 2;
                m_Points.ForEach(o => o.Offset(m_Center));
            }
        }
        public override IEnumerable<XElement> ToXml()
        {
            //检查line和point数据是否正确
            List<Line> lines = m_house.Item<Lines>().m_Lines;
            if (!m_Points.All(o => o.refCount == lines.Where(t => t.V0 == o || t.V1 == o).Count()))
            {
                var test = m_Points.Select(o => new { A = o.refCount, B = lines.Where(t => t.V0 == o || t.V1 == o).Count() });
                m_Points.ForEach(o => o.refCount = lines.Where(t => t.V0 == o || t.V1 == o).Count());
            }

            int idx = 0;
            foreach (Point pt in m_Points)
                yield return new XElement("_" + idx++, pt.ToMirror().ToXml());
        }
        public override IEnumerable<BspObject> FromXml(XElement node)
        {
            int idx = 0;
            foreach (XElement it in node.Elements())
            {
                Point point = new Point();
                point.FromXml(it);
                yield return point;
            }
        }
    }
}
